package com.xuzao.developer.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xuzao.developer.annotation.FieldNameAnnotation;
import com.xuzao.developer.base.model.DevelopPlan;
import com.xuzao.developer.base.model.PlanUpdateLog;
import com.xuzao.developer.dao.DevelopPlanDao;
import com.xuzao.developer.dao.PlanUpdateLogDao;
import com.xuzao.developer.dto.DevelopPlanDTO;
import com.xuzao.developer.enums.DevelopPlanStatusEnum;
import com.xuzao.developer.service.DevelopPlanService;
import com.xuzao.developer.utils.DateUtil;
import com.xuzao.developer.utils.IntegerUtil;
import com.xuzao.developer.utils.LoginUserInfoUtil;
import com.xuzao.developer.vo.BaseResultVo;
import com.xuzao.developer.vo.DevelopPlanVO;
import com.xuzao.developer.tools.entity.Pager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;


/**
 * @author xuzao
 * @description
 * @date 2019-08-09 18:11:13
 **/
@Service("developPlanService")
public class DevelopPlanServiceImpl implements DevelopPlanService {

    @Resource
    private DevelopPlanDao developPlanDao;
    @Resource
    private PlanUpdateLogDao planUpdateLogDao;

    @Override
    public List<DevelopPlanVO> list(DevelopPlanDTO dto, Pager pager) {
        List<DevelopPlan> list = developPlanDao.list(dto, pager).getList();
        List<DevelopPlanVO> listVo = Lists.newArrayList();
        if (!list.isEmpty()) {
            list.forEach(o -> {
                listVo.add(createVo(o));
            });
        }
        return listVo;
    }

    public DevelopPlanVO createVo(DevelopPlan o) {
        DevelopPlanVO vo = new DevelopPlanVO();
        BeanUtils.copyProperties(o, vo);
        if (null != o.getJavaDeveFinishTime()) {
            vo.setShowJavaDeveFinishTime(DateUtil.formatShort(o.getJavaDeveFinishTime()));
        }
        if (null != o.getJointDebugTime()) {
            vo.setShowJointDebugTime(DateUtil.formatShort(o.getJointDebugTime()));
        }
        if (null != o.getTestFinishTime()) {
            vo.setShowTestFinishTime(DateUtil.formatShort(o.getTestFinishTime()));
        }
        if(null != o.getTestStartTime()){
            vo.setShowTestStartTime(DateUtil.formatShort(o.getTestStartTime()));
        }
        if (null != o.getStatus()){
            vo.setShowStatus(DevelopPlanStatusEnum.valueOf(o.getStatus()).getDesc());
        }
        return vo;
    }

    @Override
    public BaseResultVo insert(DevelopPlanDTO dto) {
        DevelopPlan developPlan = new DevelopPlan();
        BeanUtils.copyProperties(dto, developPlan);
        developPlan.setJavaDeveFinishTime(DateUtil.parse(dto.getShowJavaDeveFinishTime()));
        if (StringUtils.isNotBlank(dto.getShowJointDebugTime())) {
            developPlan.setJointDebugTime(DateUtil.parse(dto.getShowJointDebugTime()));
        }
        if (StringUtils.isNotBlank(dto.getShowTestFinishTime())) {
            developPlan.setTestFinishTime(DateUtil.parse(dto.getShowTestFinishTime()));
        }
        if (StringUtils.isNotBlank(dto.getShowJointDebugTime())) {
            developPlan.setJointDebugTime(DateUtil.parse(dto.getShowJointDebugTime()));
        }
        if (StringUtils.isNotBlank(dto.getShowTestStartTime())) {
            developPlan.setTestStartTime(DateUtil.parse(dto.getShowTestStartTime()));
        }

        Integer count = developPlanDao.insertSelective(developPlan);
        if (count > 0) {
            return BaseResultVo.success();
        }
        return BaseResultVo.error();

    }

    @Override
    public BaseResultVo update(DevelopPlanDTO dto) {
        DevelopPlan oldPlan = developPlanDao.selectById(dto.getId());

        List<Map<String,String>> oldMap = convertToMap(oldPlan);

        DevelopPlan developPlan = new DevelopPlan();
        BeanUtils.copyProperties(dto, developPlan);
        developPlan.setJavaDeveFinishTime(DateUtil.parse(dto.getShowJavaDeveFinishTime()));
        if (StringUtils.isNotBlank(dto.getShowJointDebugTime())) {
            developPlan.setJointDebugTime(DateUtil.parse(dto.getShowJointDebugTime()));
        }
        if (StringUtils.isNotBlank(dto.getShowTestFinishTime())) {
            developPlan.setTestFinishTime(DateUtil.parse(dto.getShowTestFinishTime()));
        }
        if (StringUtils.isNotBlank(dto.getShowJointDebugTime())) {
            developPlan.setJointDebugTime(DateUtil.parse(dto.getShowJointDebugTime()));
        }
        if (StringUtils.isNotBlank(dto.getShowTestStartTime())) {
            developPlan.setTestStartTime(DateUtil.parse(dto.getShowTestStartTime()));
        }
        developPlan.setProjectId(oldPlan.getProjectId());
        Integer count = developPlanDao.updateById(developPlan);
        if (count > 0) {
            DevelopPlan newPlan = developPlanDao.selectById(dto.getId());
            List<Map<String,String>> newMap = convertToMap(newPlan);

            List<PlanUpdateLog> planUpdateLogs = Lists.newArrayList();

            for (int i = 0; i < oldMap.size(); i++) {
                Map<String,String> o = oldMap.get(i);
                Map<String,String> n = newMap.get(i);
                String oldVal = o.get("val");
                String newVal = n.get("val");
                
                String desc = o.get("desc");

                if (IntegerUtil.notEqualTo(oldVal,newVal)){
                    PlanUpdateLog planUpdateLog = new PlanUpdateLog();
                    planUpdateLog.setNewVal(newVal);
                    planUpdateLog.setOldVal(oldVal);
                    planUpdateLog.setUpdateKey(desc);
                    planUpdateLog.setUpdateId(LoginUserInfoUtil.getLoginUser().getId());
                    planUpdateLog.setUpdateName(LoginUserInfoUtil.getLoginUser().getRealName());
                    planUpdateLog.setProjectId(oldPlan.getProjectId());
                    planUpdateLog.setCreateTime(new Date());
                    planUpdateLogs.add(planUpdateLog);
                }
            }
            if (!planUpdateLogs.isEmpty()){
                planUpdateLogs.forEach(o->{
                    planUpdateLogDao.insert(o);
                });
            }

            return BaseResultVo.success();
        }
        return BaseResultVo.error();
    }

    public static List<Map<String,String>> convertToMap(Object obj){
        List<Map<String,String>> list = Lists.newArrayList();
        Field[] fields = obj.getClass().getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            try {
                FieldNameAnnotation annotation = field.getAnnotation(FieldNameAnnotation.class);
                Map<String,String> map = Maps.newHashMap();
                if (annotation != null) {
                    String val = "";
                    String name = field.getName();
                    Object o = field.get(obj);
                    if (null != o){
                        if (o instanceof Date){
                            val = DateUtil.formatShort((Date)o);
                        }else{
                            val = o.toString();
                        }

                        if (IntegerUtil.equalTo(name,"dayRate")){
                            val = val+"%";
                        }
                        if (IntegerUtil.equalTo(name,"status")){
                            val = DevelopPlanStatusEnum.valueOf(Integer.valueOf(val)).getDesc();
                        }
                    }
                    map.put("name",name);
                    map.put("val",val);
                    map.put("desc",annotation.name());
                    list.add(map);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    @Override
    public DevelopPlanVO get(DevelopPlanDTO dto) {
        DevelopPlanVO developPlanVO = new DevelopPlanVO();
        DevelopPlan developPlan = developPlanDao.selectById(dto.getId());
        return createVo(developPlan);
    }

    @Override
    public void del(Long id) {
        developPlanDao.deleteById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertByList(List<DevelopPlanDTO> list) {
        if (!list.isEmpty()){
            list.forEach(o->{
                insert(o);
            });
        }
    }
}